/*
 * MIT License
 *
 * Copyright (c) 2023 北京凯特伟业科技有限公司
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.je.common.base.mapper.query;

import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.je.ibatis.extension.conditions.ConditionsWrapper;

import java.io.Serializable;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

/**
 * 本地查询
 */
public class NativeQuery implements Serializable {

    private static final long serialVersionUID = 1L;

    private volatile boolean isEmpty = true;

    /**
     * 资源表名
     */
    private String tableCode;
    /**
     * sql
     */
    private String sqlBuffer = new String();
    /**
     * sql params
     */
    private List<Object> params = Lists.newArrayList();

    /**
     * 查询条件集合
     */
    private List<Condition> conditions = Lists.newArrayList();

    /**
     * 排序
     */
    private List<Order> orders = Lists.newArrayList();

    /**
     * group by
     */
    private List<GroupBy> groupBys = Lists.newArrayList();

    public String getTableCode() {
        return tableCode;
    }

    public List<Condition> getConditions() {
        return conditions;
    }

    public List<Order> getOrders() {
        return orders;
    }

    public List<GroupBy> getGroupBys() {
        return groupBys;
    }

    public String getSqlBuffer() {
        return sqlBuffer;
    }

    public void setSqlBuffer(String sqlBuffer) {
        this.sqlBuffer = sqlBuffer;
    }

    public List<Object> getParams() {
        return params;
    }

    public void setParams(List<Object> params) {
        this.params = params;
    }

    public void setTableCode(String tableCode) {
        this.tableCode = tableCode;
    }

    public void setConditions(List<Condition> conditions) {
        this.conditions = conditions;
    }

    public void setOrders(List<Order> orders) {
        this.orders = orders;
    }

    public void setGroupBys(List<GroupBy> groupBys) {
        this.groupBys = groupBys;
    }

    public boolean isEmpty() {
        return isEmpty;
    }

    /**
     * sql
     * @param sql
     * @return
     */
    public NativeQuery sql(String sql){
        if(!Strings.isNullOrEmpty(sql)){
            isEmpty = false;
            sqlBuffer += " " + sql;
        }
        return this;
    }

    /**
     * params
     * @param params
     * @return
     */
    public NativeQuery params(List<Object> params){
        if(params != null && !params.isEmpty()){
            isEmpty = false;
            params.addAll(params);
        }
        return this;
    }

    /**
     * sql with params
     * @param sql
     * @param params
     * @return
     */
    public NativeQuery sqlWithParams(String sql,List<Object> params){
        boolean flag = false;
        if(!Strings.isNullOrEmpty(sql)){
            flag = true;
            sqlBuffer += " " + sql;
        }
        if(params != null && !params.isEmpty()){
            flag = true;
            this.params.addAll(params);
        }
        if(flag){
            isEmpty = false;
        }
        return this;
    }

    /**
     * 资源表名
     * @param tableCode
     * @return
     */
    public NativeQuery tableCode(String tableCode){
        this.tableCode = tableCode;
        return this;
    }

    /**
     * and
     * @param column 字段名
     * @param value 字段值
     * @return
     */
    public NativeQuery and(String column, Condition value){
        addCondition(new Condition(column,ConditionEnum.AND.getType(),value));
        return this;
    }

    /**
     * and
     * @param column 字段名
     * @param value 字段值
     * @return
     */
    public NativeQuery and(String column, int value){
        addCondition(new Condition(column,ConditionEnum.AND.getType(),value));
        return this;
    }

    /**
     * and
     * @param column 字段名
     * @param value 字段值
     * @return
     */
    public NativeQuery and(String column, String value){
        addCondition(new Condition(column,ConditionEnum.AND.getType(),value));
        return this;
    }

    /**
     * and
     * @param column 字段名
     * @param value 字段值
     * @return
     */
    public NativeQuery and(String column, Object value){
        addCondition(new Condition(column,ConditionEnum.AND.getType(),value));
        return this;
    }

    /**
     * or
     * @param column 字段名
     * @param value 字段值
     * @return
     */
    public NativeQuery or(String column, Condition value){
        addCondition(new Condition(column,ConditionEnum.OR.getType(),value));
        return this;
    }

    /**
     * or
     * @param column 字段名
     * @param value 字段值
     * @return
     */
    public NativeQuery or(String column, int value){
        addCondition(new Condition(column,ConditionEnum.OR.getType(),value));
        return this;
    }

    /**
     * or
     * @param column 字段名
     * @param value 字段值
     * @return
     */
    public NativeQuery or(String column, String value){
        addCondition(new Condition(column,ConditionEnum.OR.getType(),value));
        return this;
    }

    /**
     * or
     * @param column 字段名
     * @param value 字段值
     * @return
     */
    public NativeQuery or(String column, Object value){
        addCondition(new Condition(column,ConditionEnum.OR.getType(),value));
        return this;
    }

    /**
     * 等于
     * @param column 字段名
     * @param value 字段值
     * @return
     */
    public NativeQuery eq(String column, Object value){
        addCondition(new Condition(column,ConditionEnum.EQ.getType(),value));
        return this;
    }

    /**
     * 大于
     * @param column 字段名
     * @param value 字段值
     * @return
     */
    public NativeQuery gt(String column, Object value){
        addCondition(new Condition(column,ConditionEnum.GT.getType(),value));
        return this;
    }

    /**
     * 大于等于
     * @param column 字段名
     * @param value 字段值
     * @return
     */
    public NativeQuery ge(String column, Object value){
        addCondition(new Condition(column,ConditionEnum.GE.getType(),value));
        return this;
    }

    /**
     * 小于
     * @param column 字段名
     * @param value 字段值
     * @return
     */
    public NativeQuery lt(String column, Object value){
        addCondition(new Condition(column,ConditionEnum.LT.getType(),value));
        return this;
    }

    /**
     * 小于等于
     * @param column 字段名
     * @param value 字段值
     * @return
     */
    public NativeQuery le(String column, Object value){
        addCondition(new Condition(column,ConditionEnum.LE.getType(),value));
        return this;
    }

    /**
     * 不等于
     * @param column 字段名
     * @param value 字段值
     * @return
     */
    public NativeQuery ne(String column, Object value){
        addCondition(new Condition(column,ConditionEnum.NE.getType(),value));
        return this;
    }

    /**
     * IS NULL
     * @param column 字段名
     * @return
     */
    public NativeQuery isNull(String column){
        addCondition(new Condition(column,ConditionEnum.IS_NULL.getType(),null));
        return this;
    }

    /**
     * IS NOT NULL
     * @param column 字段名
     * @return
     */
    public NativeQuery notNull(String column){
        addCondition(new Condition(column,ConditionEnum.NOT_NULL.getType(),null));
        return this;
    }

    /**
     * IN
     * @param column 字段名
     * @param value 字段值
     * @return
     */
    public NativeQuery in(String column, Collection<?> value){
        addCondition(new Condition(column,ConditionEnum.IN.getType(),value));
        return this;
    }

    /**
     * IN
     * @param column 字段名
     * @param value 字段值
     * @return
     */
    public NativeQuery in(String column, Object... value){
        addCondition(new Condition(column,ConditionEnum.IN.getType(),value));
        return this;
    }

    /**
     * NOT IN
     * @param column 字段名
     * @param value 字段值
     * @return
     */
    public NativeQuery notIn(String column, Object value){
        addCondition(new Condition(column,ConditionEnum.NOT_IN.getType(),value));
        return this;
    }

    /**
     * IN SELECT
     * @param column 字段名
     * @param value 字段值
     * @return
     */
    public NativeQuery inSelect(String column, Object value){
        addCondition(new Condition(column,ConditionEnum.IN_SELECT.getType(),value));
        return this;
    }

    /**
     * NOT IN SELECT
     * @param column 字段名
     * @param value 字段值
     * @return
     */
    public NativeQuery notInSelect(String column, Object value){
        addCondition(new Condition(column,ConditionEnum.NOT_IN_SELECT.getType(),value));
        return this;
    }

    /**
     * beween
     * @param column 字段名
     * @param value 字段值
     * @return
     */
    public NativeQuery beween(String column, Object value){
        addCondition(new Condition(column,ConditionEnum.BETWEEN.getType(),value));
        return this;
    }

    /**
     * left like
     * @param column 字段名
     * @param value 字段值
     * @return
     */
    public NativeQuery likeLeft(String column, Object value){
        addCondition(new Condition(column,ConditionEnum.LIKE_LEFT.getType(),value));
        return this;
    }

    /**
     * right like
     * @param column 字段名
     * @param value 字段值
     * @return
     */
    public NativeQuery likeRight(String column, Object value){
        addCondition(new Condition(column,ConditionEnum.LIKE_RIGHT.getType(),value));
        return this;
    }

    /**
     * like
     * @param column 字段名
     * @param value 字段值
     * @return
     */
    public NativeQuery like(String column, Object value){
        addCondition(new Condition(column,ConditionEnum.LIKE.getType(),value));
        return this;
    }

    /**
     * ASC排序
     * @param column
     * @return
     */
    public NativeQuery order(String column){
        addOrder(new Order(column));
        return this;
    }

    /**
     * 排序，按照类型排序，ASC
     * @param column
     * @return
     */
    public NativeQuery orderByAsc(String column){
        addOrder(new Order(column,"ASC"));
        return this;
    }

    /**
     * 排序，按照类型排序，DESC
     * @param column
     * @return
     */
    public NativeQuery orderByDesc(String column){
        addOrder(new Order(column,"DESC"));
        return this;
    }

    /**
     * 排序，按照类型排序，DESC
     * @param columns
     * @return
     */
    public NativeQuery groupBy(String... columns){
        for (String eachGroupBy:columns) {
            addGroupBy(new GroupBy(eachGroupBy));
        }
        return this;
    }

    /**
     * 增加条件
     * @param condition 条件
     * @return
     */
    public NativeQuery addCondition(Condition condition){
        isEmpty = false;
        conditions.add(condition);
        return this;
    }

    /**
     * 增加排序
     * @param order 排序条件
     * @return
     */
    public NativeQuery addOrder(Order order){
        isEmpty = false;
        orders.add(order);
        return this;
    }

    /**
     * 增加分组
     * @param groupBy 分组条件
     * @return
     */
    public NativeQuery addGroupBy(GroupBy groupBy){
        isEmpty = false;
        groupBys.add(groupBy);
        return this;
    }

    public NativeQuery apply(String sql){
        return sql(sql);
    }

    public NativeQuery applyWithParams(String sql,Object... params){
        return sqlWithParams(sql, Arrays.asList(params));
    }

    /**
     * 查询构建者
     * @return
     */
    public static NativeQuery build(){
        return new NativeQuery();
    }

    /**
     * 转换为Wrapper
     * @return
     */
    public ConditionsWrapper toWrapper(){
        ConditionsWrapper wrapper = ConditionsWrapper.builder();
        wrapper.table(tableCode);
        
        return null;
    }

}
